/*
 * @(#)XfmtRulebase.java        2003/01/01
 *
 * This file is part of Xfuzzy 3.0, a design environment for fuzzy logic
 * based systems.
 *
 * (c) 2000 IMSE-CNM. The authors may be contacted by the email address:
 *                    xfuzzy-team@imse.cnm.es
 *
 * Xfuzzy is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by
 * the Free Software Foundation.
 *
 * Xfuzzy is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * for more details.
 */

package xfuzzy.xfmt;

import xfuzzy.lang.*;
import xfuzzy.util.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

/**
 * Panel para monitorizar un m�diulo difuso
 * 
 * @author Francisco Jos� Moreno Velo
 *
 */
public class XfmtRulebase extends JDialog implements WindowListener {
	
	//----------------------------------------------------------------------------//
	//                            CONSTANTES PRIVADAS                             //
	//----------------------------------------------------------------------------//
	
	/**
	 * C�digo asociado a la clase serializable
	 */
	private static final long serialVersionUID = 95505666603048L;
	
	//----------------------------------------------------------------------------//
	//                            MIEMBROS PRIVADOS                              //
	//----------------------------------------------------------------------------//

	/**
	 * Referencia a la p�gina principal de la aplicaci�n
	 */
	private Xfmt xfmt;
	
	/**
	 * M�dulo difuso a representar
	 */
	private RuleSetCall call;
	
	/**
	 * Base de conocimiento a representar
	 */
	private RuleSet ruleset;
	
	/**
	 * Paneles para representar las variables de salida
	 */
	private XfmtOutputPanel outputpanel[];
	
	/**
	 * Paneles para representar las variables de entrada
	 */
	private XfmtInputPanel inputpanel[];
	
	/**
	 * Campos de texto para mostrar las reglas
	 */
	private XTextForm rule[];
	
	//----------------------------------------------------------------------------//
	//                                CONSTRUCTOR                                 //
	//----------------------------------------------------------------------------//

	/**
	 * Constructor
	 */
	public XfmtRulebase(Xfmt xfmt, RuleSetCall call){
		super(xfmt,"Xfmt",false);
		this.xfmt = xfmt;
		this.call = call;
		this.ruleset = (RuleSet) call.getRulebase();
		build(xfmt);
		refresh();
	}
	
	//----------------------------------------------------------------------------//
	//                             M�TODOS P�BLICOS                               //
	//----------------------------------------------------------------------------//
	
	/**
	 * Devuelve la referencia al m�dulo difuso
	 */
	public RuleSetCall getCall() {
		return this.call;
	}
	
	/**
	 * Actualiza el contenido de la ventana
	 */
	public void refresh() {
		MemFunc result[] = call.getFuzzyValues();
		MemFunc trueresult[] = call.getTrueValues();
		MemFunc inputmf[] = call.getInputValues();
		
		for(int i=0; i<inputmf.length; i++) inputpanel[i].setFunction(inputmf[i]);
		
		for(int i=0; i<result.length; i++) {
			if(trueresult[i] instanceof xfuzzy.pkg.xfl.mfunc.singleton) {
				double val = ((xfuzzy.pkg.xfl.mfunc.singleton) trueresult[i]).get()[0];
				outputpanel[i].setFunction(result[i],val);
			}
			else outputpanel[i].setFunction(result[i]);
		}
		
		double degree[] = call.getDegree();
		for(int i=0; i<degree.length; i++) rule[i].setText(redondeo(degree[i]));
		repaint();
	}
	
	/**
	 * Interfaz WindowListener. Acci�n al abrir la ventana
	 */
	public void windowOpened(WindowEvent e) {
	}

	/**
	 * Interfaz WindowListener. Acci�n al cerrar la ventana
	 */
	public void windowClosing(WindowEvent e) {
		xfmt.closeMonitor(this);
	}

	/**
	 * Interfaz WindowListener. Acci�n al finalizar el cierre
	 */
	public void windowClosed(WindowEvent e) {
	}

	/**
	 * Interfaz WindowListener. Acci�n al minimizar la ventana
	 */
	public void windowIconified(WindowEvent e) {
	}

	/**
	 * Interfaz WindowListener. Acci�n al maximizar la ventana
	 */
	public void windowDeiconified(WindowEvent e) {
	}

	/**
	 * Interfaz WindowListener. Acci�n al activar la ventana
	 */
	public void windowActivated(WindowEvent e) {
	}
	
	/**
	 * Interfaz WindowListener. Acci�n al desactivar la ventana
	 */
	public void windowDeactivated(WindowEvent e) {
	}
		
	//----------------------------------------------------------------------------//
	//                             M�TODOS PRIVADOS                               //
	//----------------------------------------------------------------------------//
	
	/**
	 * Construye la ventana
	 */
	private void build(Frame frame) {
		Box box = new Box(BoxLayout.X_AXIS);
		box.add(buildInputBox());
		box.add(Box.createHorizontalStrut(5));
		box.add(buildRuleBox());
		box.add(Box.createHorizontalStrut(5));
		box.add(buildOutputBox());
		
		Container content = getContentPane();
		content.setLayout(new BoxLayout(content,BoxLayout.Y_AXIS));
		content.add(new XLabel("Rulebase " + ruleset.getName()));
		content.add(box);
		
		setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
		addWindowListener(this);
		setFont(XConstants.font);
		setLocationRelativeTo(frame);
		
		int il = ruleset.getInputs().length;
		int ol = ruleset.getOutputs().length;
		int height = (il > ol? il*145 : ol*145);
		if(height < 320) height = 320;
		setSize(770,height);
	}
	
	/**
	 * Construye el �rea de variables de entrada
	 */
	private Box buildInputBox() {
		Box inputbox = new Box(BoxLayout.Y_AXIS);
		inputbox.add(new XLabel("Input values"));
		inputbox.add(Box.createVerticalStrut(5));
		
		Variable input[] = ruleset.getInputs();
		inputpanel = new XfmtInputPanel[input.length];
		XLabel inputlabel[] = new XLabel[input.length];
		for(int i=0; i<input.length; i++) {
			inputpanel[i] = new XfmtInputPanel(250,80,input[i]);
			inputlabel[i] = new XLabel(input[i].getName());
			
			inputbox.add(inputpanel[i]);
			inputbox.add(Box.createVerticalStrut(5));
			inputbox.add(inputlabel[i]);
			inputbox.add(Box.createVerticalGlue());
		}
		return inputbox;
	}
	
	/**
	 * Construye el �rea que muestra las reglas
	 */
	private Box buildRuleBox() {
		rule = new XTextForm[ruleset.getRules().length];
		
		JPanel panel = new JPanel();
		panel.setLayout(new BoxLayout(panel,BoxLayout.Y_AXIS));
		for(int i=0; i<rule.length; i++) {
			rule[i] = new XTextForm("Rule "+i);
			rule[i].setLabelWidth(100);
			rule[i].setFieldWidth(150);
			rule[i].setAlignment(JLabel.CENTER);
			rule[i].setEditable(false);
			panel.add(rule[i]);
		}
		
		Box rulebox = new Box(BoxLayout.Y_AXIS);
		rulebox.add(new XLabel("Rule activation degrees"));
		rulebox.add(Box.createVerticalStrut(5));
		rulebox.add(new JScrollPane(panel));
		return rulebox;
	}
	
	/**
	 * Construye el �rea de variables de salida	
	 */
	private Box buildOutputBox() {
		Box outputbox = new Box(BoxLayout.Y_AXIS);
		outputbox.add(new XLabel("Output values"));
		outputbox.add(Box.createVerticalGlue());
		outputbox.add(Box.createVerticalStrut(5));
		
		Variable output[] = ruleset.getOutputs();
		outputpanel = new XfmtOutputPanel[output.length];
		XLabel outputlabel[] = new XLabel[output.length];
		for(int i=0; i<output.length; i++) {
			outputpanel[i] = new XfmtOutputPanel(250,80,output[i]);
			outputlabel[i] = new XLabel(output[i].getName());
			
			outputbox.add(outputpanel[i]);
			outputbox.add(Box.createVerticalStrut(5));
			outputbox.add(outputlabel[i]);
			outputbox.add(Box.createVerticalGlue());
		}
		return outputbox;
	}
	
	/**
	 * Devuelve la cadena que representa el n�mero con 6 digitos
	 */
	private String redondeo(double dd) {
		String data = ""+dd;
		char[] cdat = data.toCharArray();
		int i;
		for(i=0; i<cdat.length; i++) if(cdat[i]>'0' && cdat[i]<='9') break;
		for(int j=0; j<6 && i<cdat.length; j++,i++)
			if(cdat[i]=='e' || cdat[i]=='E') break;
		StringBuffer buf = new StringBuffer(data.substring(0,i));
		int e = data.indexOf("E");
		if(e == -1) e = data.indexOf("e");
		if(e != -1) buf.append(data.substring(e));
		return buf.toString();
	}
}
